package com.xue.geo.area;

import com.xue.domain.AreaInfo;
import com.xue.geo.domain.Coordinate;
import com.xue.geo.domain.Point;
import com.xue.utils.LatLonUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;

/**
 * @author xue
 * @create 2022-09-16 17:30
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class TriangleAreaJudge extends AreaJudge {

    private static final double SQRT_3 = Math.sqrt(3);
    private static final BigDecimal Y_INCREMENTAL = BigDecimal.valueOf(0.577350269);
    private static final BigDecimal Y_DECREMENT = BigDecimal.valueOf(0.288675134);

    private Point coordinateA;
    private Point coordinateB;
    private Point coordinateC;

    @Override
    public AreaJudge createArea(AreaInfo areaBase) {
        Integer lat = areaBase.getLat();
        Integer lon = areaBase.getLon();

        BigDecimal side = BigDecimal.valueOf(areaBase.getLdm())
                // 转换成米
                .divide(BigDecimal.valueOf(1000), 3, BigDecimal.ROUND_HALF_UP)
                // 转换成偏移度数
                .multiply(PROPORTION).setScale(0, BigDecimal.ROUND_HALF_UP);

        /*BigDecimal yVariable = side.divide(BigDecimal.valueOf(SQRT_3), 0, BigDecimal.ROUND_HALF_UP);
        int yIncremental = yVariable.intValue();
        coordinateA = new Point(lon, lat + yIncremental);

        int sideHalf = side.divide(BigDecimal.valueOf(2), 0, BigDecimal.ROUND_HALF_UP).intValue();
        int yDecrement = yVariable.divide(BigDecimal.valueOf(2), 0, BigDecimal.ROUND_HALF_UP).intValue();

        coordinateB = new Point(lon + sideHalf, lat - yDecrement);
        coordinateC = new Point(lon - sideHalf, lat - yDecrement);*/

        int yIncremental = side.multiply(Y_INCREMENTAL).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
        int yDecrement = side.multiply(Y_DECREMENT).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
        int sideHalf = side.divide(BigDecimal.valueOf(2), 0, BigDecimal.ROUND_HALF_UP).intValue();

        coordinateA = new Point(lon, lat + yIncremental);
        coordinateB = new Point(lon + sideHalf, lat - yDecrement);
        coordinateC = new Point(lon - sideHalf, lat - yDecrement);

        return this;
    }

    @Override
    public Boolean pointInside(Coordinate coordinate) {
        // 利用叉乘法进行判断,假设P点就是M点
        Point cPoint = new Point(LatLonUtil.translationPoint(coordinate.getLongitude()), LatLonUtil.translationPoint(coordinate.getLatitude()));
        // 利用叉乘法进行判断,假设P点就是M点
        Point ma = new Point(cPoint.getX() - coordinateA.getX(), cPoint.getY() - coordinateA.getY());
        Point mb = new Point(cPoint.getX() - coordinateB.getX(), cPoint.getY() - coordinateB.getY());
        Point mc = new Point(cPoint.getX() - coordinateC.getX(), cPoint.getY() - coordinateC.getY());
        // 向量叉乘
        int a = ma.getX() * mb.getY() - ma.getY() * mb.getX();
        int b = mb.getX() * mc.getY() - mb.getY() * mc.getX();
        int c = mc.getX() * ma.getY() - mc.getY() * ma.getX();
        if ((a <= 0 && b <= 0 && c <= 0) || (a > 0 && b > 0 && c > 0)) {
            return true;
        }
        return false;
    }
}
